package com.luoke.connect;

import cn.hutool.json.JSONUtil;
import com.luoke.constants.ModuleTypeConstant;
import com.luoke.context.UserContext;
import com.luoke.handler.request.UserRequestHandler;
import com.luoke.handler.response.BattleResponseHandler;
import com.luoke.handler.response.BattleRoundResponseHandle;
import com.luoke.handler.response.UserResponseHandler;
import com.luoke.result.Result;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 该类是与服务端的连接类，通信主类
 */
public class GameWebSocketClient extends WebSocketClient {
    private UserRequestHandler userRequestHandler = new UserRequestHandler();
    private UserResponseHandler userResponseHandler = new UserResponseHandler();
    private BattleResponseHandler battleResponseHandler = new BattleResponseHandler();
    private BattleRoundResponseHandle battleRoundResponseHandle = new BattleRoundResponseHandle();
    private Timer heartbeatTimer;

    /**
     * 向服务端发起连接的uri
     *
     * @param serverUri 服务端的uri
     */
    public GameWebSocketClient(URI serverUri) {
        super(serverUri);
    }


    /**
     * 当连接建立时调用
     *
     * @param handshakedata websocket实例的握手，服务器在 WebSocket 握手阶段返回的信息，它通常包含握手的相关数据
     */
    @Override
    public void onOpen(ServerHandshake handshakedata) {
        //建立心跳连接
        startHeartbeat();  //这里必须要在展示菜单之前，否则会进入scanner的阻塞状态导致心跳机制无法正常执行，导致客户端的断联
        //当连接建立的时候，展示登录菜单
        userRequestHandler.showLoginMenu(this);

    }


    /**
     * 当收到服务器消息时调用
     *
     * @param message 服务端返回的消息，一般采用JSON格式
     */
    @Override
    public void onMessage(String message) {
//        if ("pong".equals(message)) {
//            //拿到客户端的心跳响应，可不处理
////            System.out.println("Heartbeat response received: pong");
//            return;
//        }

        Result result = JSONUtil.toBean(message, Result.class);
        if (result.getModuleName().equals(ModuleTypeConstant.USER)) { //判断响应模块 进行分发处理
            userResponseHandler.handler(this, result);
        } else if (result.getModuleName().equals(ModuleTypeConstant.BATTLE)) {
            battleResponseHandler.handler(this, result);
        } else if (result.getModuleName().equals(ModuleTypeConstant.BATTLE_ROUND)) {
            battleRoundResponseHandle.handler(this, result);
        }
    }


    /**
     * 当连接关闭时调用
     *
     * @param code   这个参数表示关闭连接的状态码
     * @param reason 表示关闭连接的原因
     * @param remote true：表示连接是由远程主机（服务器）主动关闭的。false：表示连接是由本地主机（客户端）主动关闭的
     */
    @Override
    public void onClose(int code, String reason, boolean remote) {

        UserContext.clear();  //把用户从上下文中移除
        stopHeartbeat(); // 关闭连接时停止心跳
    }


    /**
     * 该方法在连接发生异常时被调用，可以用于处理和记录异常信息
     *
     * @param ex 这是导致 WebSocket 出现错误的异常对象
     */
    @Override
    public void onError(Exception ex) {

        //TODO 后续考虑如何进行异常处理

//            throw new RuntimeException(ex);
    }


    /**
     * 启动心跳定时器
     */
    private void startHeartbeat() {
        //创建一个定时器
        heartbeatTimer = new Timer(true);
        //创建一个定时任务
        heartbeatTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (isOpen()) {
                    send("ping");
                }
            }
        }, 0, 3000); // 每3秒发送一次心跳
    }

    /**
     *  停止心跳定时器
     */
    private void stopHeartbeat() {
        if (heartbeatTimer != null) {
            heartbeatTimer.cancel();
        }
    }
}
